package com.txzt.gaea.business.fund.service.impl;

import com.txzt.gaea.business.fund.domain.model.FundApply;
import com.txzt.gaea.business.fund.domain.model.FundBudget;
import com.txzt.gaea.business.fund.service.IFundApplyService;
import com.txzt.gaea.business.fund.service.IFundBudgetService;
import com.txzt.gaea.business.util.TranslateUtil;
import com.txzt.gaea.common.base.service.impl.BaseServiceImpl;
import com.txzt.gaea.common.enums.ApplyStatus;
import com.txzt.gaea.common.enums.FlowFlagEnum;
import com.txzt.gaea.common.enums.IsDeleteEnum;
import com.txzt.gaea.flow.service.FlowService;
import com.txzt.gaea.flow.vo.FlowBizStepVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Service
public class FundApplyServiceImpl extends BaseServiceImpl<FundApply> implements IFundApplyService {

    @Autowired
    private FlowService flowService;
    @Autowired
    private IFundBudgetService fundBudgetService;

    @Override
    public List<Map> getTotalNum(){
        return sqlManager.select("fundApply.getTotalSum",Map.class,null);
    }

    @Override
    public FundApply selectFundApplyById(Long id) {
        FundApply fundApply = sqlManager.single(FundApply.class,id);
        if (null == fundApply) {
            return null;
        }
        List<FlowBizStepVo> list = flowService.getFlowBizStep(fundApply.getFlowId());
        fundApply.setFlowStep(list);
        fundApply.setCheck(TranslateUtil.getCheck(list));
        fundApply.setDepartName(TranslateUtil.getDepartmentName(fundApply.getDepartId()));
        return fundApply;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int addFundApply(FundApply fundApply) {
        long num = sqlManager.query(FundApply.class)
                .andEq("apply_name",fundApply.getApplyName())
                .andEq("is_delete",IsDeleteEnum.NOTDELETE.getCode()).count();
        if (num > 0) {
            return 9;
        }
        FundBudget res = fundBudgetService.selectById(fundApply.getFundId());
        BigDecimal useFund = res.getUseFund().add(fundApply.getApplyAmount());
        BigDecimal remainFund = res.getRemainFund().subtract(fundApply.getApplyAmount());
        //计算经费是否超支
        if (remainFund.compareTo(BigDecimal.ZERO) < 0) {
            return 99;
        }
        //更新经费金额（扣减）
        FundBudget fundBudget = new FundBudget();
        fundBudget.setId(fundApply.getFundId());
        fundBudget.setUseFund(useFund);
        fundBudget.setRemainFund(remainFund);
        fundBudgetService.updateById(fundBudget);
        //新增经费请领
        fundApply.setApplyStatus(ApplyStatus.CHECK.getCode());
        fundApply.setIsDelete(IsDeleteEnum.NOTDELETE.getCode());
        int count = sqlManager.insertTemplate(fundApply,true);
        //开启流程
        Long flowBizId = flowService.startFlow(fundApply.getId(), "tb_fund_apply","apply_status",
                ApplyStatus.BACK.getCode(), ApplyStatus.PASS.getCode(), FlowFlagEnum.FUND_APPLY.getCode());
        FundApply target = new FundApply();
        target.setId(fundApply.getId());
        target.setFlowId(flowBizId);
        sqlManager.updateTemplateById(target);
        return count;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int editFundApply(FundApply fundApply) {
        long num = sqlManager.query(FundApply.class)
                .andEq("apply_name",fundApply.getApplyName())
                .andEq("is_delete",IsDeleteEnum.NOTDELETE.getCode())
                .andNotEq("id",fundApply.getId())
                .count();
        if (num > 0) {
            return 9;
        }
        FundBudget res = fundBudgetService.selectById(fundApply.getFundId());
        BigDecimal useFund = res.getUseFund().add(fundApply.getApplyAmount());
        BigDecimal remainFund = res.getRemainFund().subtract(fundApply.getApplyAmount());
        //计算经费是否超支
        if (remainFund.compareTo(BigDecimal.ZERO) < 0) {
            return 99;
        }
        //更新经费金额（扣减）
        FundBudget fundBudget = new FundBudget();
        fundBudget.setId(fundApply.getFundId());
        fundBudget.setUseFund(useFund);
        fundBudget.setRemainFund(remainFund);
        fundBudgetService.updateById(fundBudget);
        //开启流程
        Long flowBizId = flowService.startFlow(fundApply.getId(), "tb_fund_apply","apply_status",
                ApplyStatus.BACK.getCode(), ApplyStatus.PASS.getCode(), FlowFlagEnum.FUND_APPLY.getCode());
        fundApply.setFlowId(flowBizId);
        fundApply.setApplyStatus(ApplyStatus.CHECK.getCode());
        return sqlManager.updateTemplateById(fundApply);
    }


    @Override
    public int passFundApply(FundApply fundApply) {
        boolean flag = flowService.nextStep(fundApply.getFlowId(), 1,fundApply.getComment());
        if (flag) {
            return 1;
        }else {
            return 0;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int backFundApply(FundApply fundApply) {
        boolean flag = flowService.nextStep(fundApply.getFlowId(), 2,fundApply.getComment());
        this.calculateFund(fundApply);
        if (flag) {
            return 1;
        }else {
            return 0;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int rejectFundApply(FundApply fundApply) {
        boolean flag = flowService.nextStep(fundApply.getFlowId(), 3,fundApply.getComment());
        this.calculateFund(fundApply);
        if (flag) {
            return 1;
        }else {
            return 0;
        }
    }

    /**
     * 更新经费金额(退还)
     * @param fundApply
     */
    private void calculateFund(FundApply fundApply){
        //更新经费金额(退还)
        FundBudget res = fundBudgetService.selectById(fundApply.getFundId());
        BigDecimal useFund = res.getUseFund().subtract(fundApply.getApplyAmount());
        BigDecimal remainFund = res.getRemainFund().add(fundApply.getApplyAmount());
        FundBudget fundBudget = new FundBudget();
        fundBudget.setId(fundApply.getFundId());
        fundBudget.setUseFund(useFund);
        fundBudget.setRemainFund(remainFund);
        fundBudgetService.updateById(fundBudget);
    }
}
